package com.fingard.util;

import com.fingard.FGBiz;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptJson;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptMapping;
import com.fingard.dsp.bank.directConfig.BankConfig;
import com.fingard.dsp.tcpserver.ThreadPoolReceipt;
import com.fingard.net.WebRequest;
import net.sf.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 电子回单处理公共类
 * Alan
 * 2019/07/30
 */
public class ReceiptUtils {

    /**
     * 回单文件保存
     * @param zipFilePath：待保存的回单压缩文件
     * @return
     * @throws Exception
     */
    public static int receiptFileSave(String zipFilePath) throws Exception{
        int result = SmbFileUtil.smbUploading(zipFilePath, "/", FGBiz.dspCenter.dspSet.receiptShareDir);
        return result;
    }

    /**
     * 通过线程池上传回单文件列表
     * @param listFile
     * @return
     */
    public static Map<String,ReceiptMapping> uploadFileByThreadPool(List<ReceiptMapping> listFile,String bankCode,BankConfig bankConfig,StringBuilder sbLog){
        Map<String,ReceiptMapping> mappingMap=new HashMap<String, ReceiptMapping>();
        //获取线程数
        int corePoolSize=FGBiz.dspCenter.dspSet.corePoolSize;
        int maximumPoolSize=FGBiz.dspCenter.dspSet.maximumPoolSize;
        //创建一个线程池
        ThreadPoolExecutor executorService = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
                200, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<Runnable>(maximumPoolSize));
        //分组
        Map<Integer,List<ReceiptMapping>> map=avgGrouping(listFile,executorService.getCorePoolSize());
        sbLog.append("*****************开启线程池开始上传文件*****************");
        //开启线程池上传文件
        for(Map.Entry<Integer, List<ReceiptMapping>> m : map.entrySet()){
            ThreadPoolReceipt thread = new ThreadPoolReceipt(m.getKey(),m.getValue(),bankCode,bankConfig);
            executorService.execute(thread);
            sbLog.append("线程池中线程数目："+executorService.getPoolSize()+"，队列中等待执行的任务数目："+
                    executorService.getQueue().size()+"，已执行完别的任务数目："+executorService.getCompletedTaskCount());
        }
        executorService.shutdown();
        //等待线程池线程全部结束，获取上传成功的回单
        while (true) {
            if (executorService.isTerminated()) {
                sbLog.append(ThreadPoolReceipt.getRunLog().toString());
                //获取上传成功的map
                mappingMap=ThreadPoolReceipt.getMap();
                break;
            }
        }
        return mappingMap;
    }

    /**
     * 推送回单至ats逻辑
     * @param jsonList 推送回单信息
     * @return
     * @throws Exception
     */
    public static int[] receiptFileToAts(List<StringBuilder> jsonList) throws Exception {
        int[] resultArr=new int[]{0,0};//推送结果
        int numSuccess=0;//推送成功数
        int numError=0;//推送失败数
        List<StringBuilder> jsonError=new ArrayList<StringBuilder>();//推送失败记录
        StringBuilder sendStr = new StringBuilder();//主体json串
        StringBuilder sendJson = new StringBuilder();//部分json串
        int receiptDataCount = FGBiz.dspCenter.dspSet.receiptToAtsBatchNum;//分批推送ats的回单文件数量
        if (jsonList.size() > 0) {
            sendStr.append("transType=downloadreceipt&data={\"rows\":[");
            for (int i = 0; i < jsonList.size(); i++) {
                if ((i + 1) % receiptDataCount == 0 || i == jsonList.size() - 1) {
                    //推送数据拼接
                    jsonList.get(i).deleteCharAt(jsonList.get(i).length() - 1);
                    sendJson.append(jsonList.get(i));
                    sendJson.append("]}");
                    //推送ats请求
                    String[] data = sendToATS(sendStr.append(sendJson));
                    //推送结果统计
                    int numTo=(i + 1) % receiptDataCount > 0 ? (i + 1) % receiptDataCount : receiptDataCount;
                    if (data[0].length() == 0 && "ok".equals(data[1])) {
                        numSuccess+= numTo;
                    } else {
                        numError+= numTo;
                        jsonError.add(sendJson);
                    }
                    sendJson = new StringBuilder();
                } else {
                    sendJson.append(jsonList.get(i));
                }
            }
        }
        //推送数量
        resultArr[0]=numSuccess;
        resultArr[1]=numError;
        //推送失败的未进行处理

        return resultArr;
    }

    /**
     * 与ats通信交互
     * @param jsonData 通信请求数据，回单信息
     * @return
     * @throws Exception
     */
    public static String[] sendToATS(StringBuilder jsonData) throws Exception {
        //发送银行前置
        WebRequest tmpRequest = new WebRequest(FGBiz.dspCenter.dspSet.receiptPushServerUrl);
        tmpRequest.setConnectTimeout(10000);
        tmpRequest.setRequestProperty("connection", "Close");
        tmpRequest.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        String charsetName = FGBiz.dspCenter.dspSet.receiptToAtsCharset;
        byte[] tmpWriteBytes = jsonData.toString().getBytes(charsetName);
        String[] retStr = tmpRequest.upload(tmpWriteBytes, charsetName);
        return retStr;
    }

    /**
     * fileList文件列表分组
     * @return
     */
    private static Map<Integer,List<ReceiptMapping>> avgGrouping(List<ReceiptMapping> listFile, int n){
        Map<Integer,List<ReceiptMapping>> map = new HashMap<Integer, List<ReceiptMapping>>();
        //根据线程池进行分组：分组规则，
        int listSize = listFile.size();//集合总数
        int toIndex = listFile.size()/n;//商
        int keyToken = 1;
        if(toIndex<=1){
            map.put(keyToken, listFile);
        }else {
            for (int i = 0; i < listFile.size(); i += toIndex) {
                if (i + toIndex*2 > listSize) {//最后的数据全部放入最后的集合中
                    toIndex = listSize-i;
                }
                List<ReceiptMapping> newList = listFile.subList(i, i + toIndex);
                map.put(keyToken, newList);
                keyToken++;
            }
        }
        return map;
    }

    /**
     * json类转string串
     * @param receiptJson
     * @return
     */
    public static String toJsonString(ReceiptJson receiptJson){
        JSONObject obj = JSONObject.fromObject(receiptJson);
        String json = obj.toString();
        return json;
    }

    /**
     * string串转json类
     * @param jsonStr
     * @return
     */
    public static ReceiptJson jsonStrToVO(String jsonStr){
        JSONObject obj = new JSONObject().fromObject(jsonStr);
        ReceiptJson receiptJson = (ReceiptJson)JSONObject.toBean(obj,ReceiptJson.class);
        return receiptJson;
    }
}
